package com.shadow.demo.dictionary.common;


import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.sql.*;
import java.util.Collection;
import java.util.Iterator;

/**
 * IO操作类
 *
 * @author penggch
 */
@Slf4j
public class IoUtil {

    public static final String Default_Charset = "UTF-8";
    private static final int BufferSize = 4096;

    public static void write(InputStream inputStream, OutputStream outputStream) {
        byte[] buffer = new byte[BufferSize];
        try {
            int count = inputStream.read(buffer, 0, buffer.length);
            while (count != -1) {
                outputStream.write(buffer, 0, count);
                count = inputStream.read(buffer, 0, buffer.length);
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public static void write(InputStream inputStream, OutputStream outputStream, long contentSize) {
        byte[] buffer = new byte[BufferSize];
        try {
            while (contentSize > 0) {
                int count = -1;
                if (contentSize > buffer.length) {
                    count = inputStream.read(buffer, 0, buffer.length);
                } else {
                    count = inputStream.read(buffer, 0, (int) contentSize);
                }
                if (count > 0) {
                    outputStream.write(buffer, 0, count);
                    contentSize = contentSize - count;
                }
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public static void write(File file, OutputStream outputStream) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            write(fis, outputStream);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(fis);
        }
    }

    public static void write(String file, OutputStream outputStream) {
        write(new File(file), outputStream);
    }

    public static void write(InputStream inputStream, File outputFile) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(outputFile);
            write(inputStream, fos);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(fos);
        }
    }

    public static void write(InputStream inputStream, File outputFile, long contentSize) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(outputFile);
            write(inputStream, fos, contentSize);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(fos);
        }
    }

    public static void write(File inputFile, File outputFile) {
        FileOutputStream fos = null;
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(inputFile);
            fos = new FileOutputStream(outputFile);
            write(fis, fos);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(fis);
            closeQuietly(fos);
        }
    }

    public static void write(String inputFile, File outputFile) {
        write(new File(inputFile), outputFile);
    }

    public static String readText(InputStream inputStream) {
        return readText(inputStream, Default_Charset);
    }

    public static String readText(InputStream inputStream, String charsetName) {
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            write(inputStream, baos);
            if (charsetName == null || charsetName.length() == 0) {
                return baos.toString();
            } else {
                return baos.toString(charsetName);
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(baos);
        }
    }

    public static String readText(File file) {
        return readText(file, Default_Charset);
    }

    public static String readText(File file, String charsetName) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            return readText(fis, charsetName);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(fis);
        }
    }

    public static String readText(String file) {
        return readText(file, Default_Charset);
    }

    public static String readText(String file, String charsetName) {
        return readText(new File(file), charsetName);
    }

    public static String readText(Clob clob) {
        try {
            if (clob == null || clob.length() == 0) {
                return null;
            }
            StringBuilder sb = new StringBuilder();
            int bufferSize = BufferSize;
            long c = clob.length() / bufferSize;
            int r = (int) (clob.length() % bufferSize);
            for (int i = 0; i < c; i++) {
                sb.append(clob.getSubString(c * i + 1, bufferSize));
            }
            if (r > 0) {
                sb.append(clob.getSubString(c * bufferSize + 1, r));
            }
            return sb.toString();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String readText(Blob blob) {
        return readText(blob, Default_Charset);
    }

    public static String readText(Blob blob, String charsetName) {
        try {
            if (blob == null || blob.length() == 0l)
                return null;
            if (charsetName == null) {
                charsetName = Default_Charset;
            }
            byte[] content = blob.getBytes(1, (int) blob.length());
            return new String(content, charsetName);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] readByte(Blob blob) {
        InputStream is = null;
        try {
            is = blob.getBinaryStream();
            return readByte(is);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(is);
        }
    }

    public static byte[] readByte(File file) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            return readByte(fis);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(fis);
        }
    }

    public static byte[] readByte(String file) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            return readByte(fis);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(fis);
        }
    }

    public static byte[] readByte(InputStream inputStream) {
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            write(inputStream, baos);
            return baos.toByteArray();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(baos);
        }
    }

    public static void writeByte(byte[] bytes, OutputStream outputStream) {
        try {
            outputStream.write(bytes);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public static void writeByte(byte[] bytes, File file) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            writeByte(bytes, fos);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(fos);
        }
    }

    public static void writeByte(byte[] bytes, String file) {
        writeByte(bytes, new File(file));
    }

    public static void writeText(String text, OutputStream outputStream) {
        writeText(text, Default_Charset, outputStream);
    }

    public static void writeText(String text, String charsetName, OutputStream outputStream) {
        try {
            if (charsetName != null && charsetName.length() > 0) {
                writeByte(text.getBytes(charsetName), outputStream);
            } else {
                writeByte(text.getBytes(), outputStream);
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public static void writeText(String text, File file) {
        writeText(text, Default_Charset, file);
    }

    public static void writeText(String text, String charsetName, File file) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            writeText(text, charsetName, fos);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(fos);
        }
    }

    public static void writeText(String text, String file) {
        writeText(text, Default_Charset, file);
    }

    public static void writeText(String text, String charsetName, String file) {
        writeText(text, charsetName, new File(file));
    }

    public static void closeQuietly(Object obj) {
        if (obj != null) {
            if (obj instanceof Closeable) {
                closeQuietly((Closeable) obj);

            } else if (obj instanceof HttpURLConnection) {
                closeQuietly((HttpURLConnection) obj);

            } else if (obj instanceof Connection) {
                closeQuietly((Connection) obj);
            } else if (obj instanceof Statement) {
                closeQuietly((Statement) obj);

            } else if (obj instanceof ResultSet) {
                closeQuietly((ResultSet) obj);

            } else {
                Method[] methods = obj.getClass().getMethods();
                if (methods != null) {
                    for (Method method : methods) {
                        if (method.getParameters() != null && method.getParameters().length > 0) {
                            continue;
                        }
                        if (method.getName().equals("close") || method.getName().equals("destroy")
                                || method.getName().equals("dispose")) {
                            try {
                                method.invoke(obj);
                            } catch (Exception e) {
                                log.warn(e.getMessage());
                            }
                        }
                    }
                }
            }
        }
    }

    public static void closeQuietly(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (IOException ioe) {
            log.error("closeQuietly", ioe);
        }
    }

    public static void closeQuietly(HttpURLConnection httpConn) {
        try {
            if (httpConn != null) {
                httpConn.disconnect();
            }
        } catch (Exception e) {
            log.error("closeQuietly", e);
        }
    }

    public static void closeQuietly(Connection conn) {
        try {
            if (conn != null && !conn.getAutoCommit()) {
                conn.rollback();
            }
        } catch (Exception e) {
            log.error("closeQuietly", e);
        }
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (Exception e) {
            log.error("closeQuietly", e);
        }
    }

    public static void closeQuietly(Statement statement) {
        try {
            if (statement != null) {
                statement.close();
            }
        } catch (Exception e) {
            log.error("closeQuietly", e);
        }
    }

    public static void closeQuietly(ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (Exception e) {
            log.error("closeQuietly", e);
        }
    }

    public static void deleteQuietly(Collection<String> files) {
        if (files == null || files.size() == 0) {
            return;
        }
        Iterator<String> ite = files.iterator();
        while (ite.hasNext()) {
            deleteQuietly(ite.next());
        }
    }

    public static void deleteQuietly(File file) {
        if (file == null || !file.exists()) {
            return;
        }
        try {
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                if (files != null && files.length > 0) {
                    for (File f : files) {
                        deleteQuietly(f);
                    }
                }
            }
            file.delete();
        } catch (Exception e) {
            log.error("deleteQuietly", e);
        }
    }

    public static void deleteQuietly(String file) {
        if (file == null || file.length() == 0) {
            return;
        }
        deleteQuietly(new File(file));
    }

    public static String readStackTrace(Throwable throwable) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try {
            throwable.printStackTrace(pw);
            return sw.toString();
        } finally {
            closeQuietly(pw);
            closeQuietly(sw);
        }
    }

    public static String readResourceText(String resourcePath) {
        return readResourceText(resourcePath, null);
    }

    public static String readResourceText(String resourcePath, String charsetName) {
        InputStream inputStream = null;
        try {
            inputStream = IoUtil.class.getClassLoader().getResourceAsStream(resourcePath);
            if (inputStream != null) {
                return readText(inputStream, charsetName);
            } else {
                return null;
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            closeQuietly(inputStream);
        }
    }

    /***
     *      String 字符串转输入流
     * @param text
     * @return
     */
    public static InputStream wirteIs(String text) {
        InputStream is = null;
        try {
            is = new ByteArrayInputStream(text.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            log.error("wirteIs", e);
        }
        return is;
    }

    public static void main(String[] args) {
        File file = new File("D:\\test\\你好1.txt");
        String charset = FileUtil.getCharset(file);
        System.out.println("args = " + charset.toString());
        String content = IoUtil.readText(file, "gbk");
        IoUtil.writeText(content, "utf-8", new File("D:\\test\\你好2.txt"));
    }

    public static void disconnectQuietly(HttpURLConnection httpUrl) {
        if (httpUrl != null) {
            try {
                httpUrl.disconnect();
            } catch (Exception e) {
                log.error("disconnectQuietly", e);
            }
        }
    }
}
